package com.lanxiao.cloud.modules.user.application.assembler;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.lanxiao.cloud.common.core.dto.ResultModel;
import com.lanxiao.cloud.common.core.dto.UserBaseDto;
import com.lanxiao.cloud.common.fill.FillHandle;
import com.lanxiao.cloud.common.fill.FillHandleFactory;
import com.lanxiao.cloud.common.fill.FillType;
import com.lanxiao.cloud.modules.user.application.dto.UserCmdUpdate;
import com.lanxiao.cloud.modules.user.application.dto.UserDeptPageDto;
import com.lanxiao.cloud.modules.user.application.dto.UserDto;
import com.lanxiao.cloud.modules.user.application.dto.UserPageDto;
import com.lanxiao.cloud.modules.user.application.dto.UserPersonalCmdUpdate;
import com.lanxiao.cloud.modules.user.domain.model.User;
import com.lanxiao.cloud.user.api.dto.LoginInfoDubboUpdate;
import com.lanxiao.cloud.user.api.dto.UserDubboAdd;
import com.lanxiao.cloud.user.api.dto.UserDubboDto;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import org.springframework.stereotype.Component;

/**
 * @author ：qiaoliang
 * @date ：2021-09-13
 */
@Component
public class UserAssembler {

  private final FillHandleFactory fillHandleFactory;

  public UserAssembler(FillHandleFactory fillHandleFactory) {
    this.fillHandleFactory = fillHandleFactory;
  }

  public UserDto toUserDto(User user){
    final UserDto userDto = UserConverter.INSTANCE.toUserDto(user);
    List<FillHandle<UserDto, ?, ?>> list = new ArrayList<>();
    list.add(new FillHandle<>(FillType.PARENT_DEPT_NAME, UserDto::setDeptName, UserDto::getDeptId));
    list.add(new FillHandle<>(FillType.ROLE_NAME, UserDto::setRoleName, UserDto::getId));
    fillHandleFactory.fill(Lists.newArrayList(userDto), list);
    return userDto;
  }

  public UserDubboDto toUserDubboDto(User user){
    return UserConverter.INSTANCE.toUserDubboDto(user);
  }

  public List<UserDto> toUserDto(List<User> list){
    final List<UserDto> userDtos = UserConverter.INSTANCE.toUserDto(list);
    List<FillHandle<UserDto, ?, ?>> fillHandles = new ArrayList<>();
    fillHandles.add(new FillHandle<>(FillType.PARENT_DEPT_NAME, UserDto::setDeptName, UserDto::getDeptId));
    fillHandles.add(new FillHandle<>(FillType.ROLE_NAME, UserDto::setRoleName, UserDto::getId));
    fillHandleFactory.fill(userDtos, fillHandles);
    return userDtos;
  }

  public ResultModel<UserPageDto> toUserPageDto(IPage<User> page){
    return new ResultModel<>(UserConverter.INSTANCE.toUserPageDto(page.getRecords()),
        (int) page.getTotal());
  }

  public ResultModel<UserDeptPageDto> toUserDeptPageDto(IPage<User> page){
    return new ResultModel<>(UserConverter.INSTANCE.toUserDeptPageDto(page.getRecords()),
        (int) page.getTotal());
  }

  public User toUser(UserDubboAdd userDubboAdd) {
    return UserConverter.INSTANCE.toUser(userDubboAdd);
  }

  public User toUser(LoginInfoDubboUpdate update) {
    return UserConverter.INSTANCE.toUser(update);
  }

  public User toUser(Long id, UserCmdUpdate update) {
    final User user = UserConverter.INSTANCE.toUser(update);
    user.setId(id);
    return user;
  }

  public User toUser(Long id, UserPersonalCmdUpdate update) {
    final User user = UserConverter.INSTANCE.toUser(update);
    user.setId(id);
    return user;
  }

  public Map<Long, UserBaseDto<Long>> toUserBaseDto(Map<Long, User> userMap) {
    Map<Long, UserBaseDto<Long>> map = new HashMap<>(userMap.size());
    userMap.forEach((k,v)-> map.put(k, UserConverter.INSTANCE.toUserBaseDto(v)));
    return map;
  }

  @Mapper
  public interface UserConverter {
    UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);

    User toUser(UserDubboAdd userDubboAdd);
    User toUser(LoginInfoDubboUpdate update);
    User toUser(UserCmdUpdate update);
    User toUser(UserPersonalCmdUpdate update);

    UserBaseDto<Long> toUserBaseDto(User user);

    UserDto toUserDto(User user);
    List<UserDto> toUserDto(List<User> list);

    UserDubboDto toUserDubboDto(User user);

    UserPageDto toUserPageDto(User user);
    List<UserPageDto> toUserPageDto(List<User> list);

    UserDeptPageDto toUserDeptPageDto(User user);
    List<UserDeptPageDto> toUserDeptPageDto(List<User> list);
  }

}
